package controller

import (
	"context"
	"fmt"
	"runtime/debug"
	"time"

	"v8s-watcher/internal/configuration"
	"v8s/logger"

	"go.uber.org/zap"
)

type (
	Scheduler struct {
		task       Task
		properties configuration.SchedulerProperties
		log        *zap.SugaredLogger
	}

	Task interface {
		Name() string
		Execute(context.Context) error
	}
)

func NewScheduler(task Task, properties configuration.SchedulerProperties) *Scheduler {
	return &Scheduler{
		task:       task,
		properties: properties,
		log:        logger.Logger().Named("scheduler-" + task.Name()).Sugar(),
	}
}

func (scheduler *Scheduler) Run() {
	for {
		scheduler.log.Debugf("starting task")

		ctx, cancel := context.WithTimeout(context.Background(), scheduler.properties.TaskExecutionTimeout)

		err := execute(ctx, scheduler.task)

		cancel()

		if err != nil {
			scheduler.log.Errorf("failed to execute task: %s", err)
		}

		scheduler.log.Debugf("task finished, going to sleep")

		time.Sleep(scheduler.properties.Timeout)
	}
}

func execute(ctx context.Context, task Task) (err error) {
	defer func() {
		recovered := recover()
		if recovered != nil {
			debug.PrintStack()
			err = fmt.Errorf("recovered from: %s", recovered)
		}
	}()

	err = task.Execute(ctx)

	return
}
